package com.guosen.zebra.framework.starter.sms.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.guosen.zebra.framework.starter.sms.config.SmsProperties;
import com.guosen.zebra.framework.starter.sms.enums.SmsApis;
import com.guosen.zebra.framework.starter.sms.exception.SmsException;
import com.guosen.zebra.framework.starter.sms.internal.SmsHttpClient;
import com.guosen.zebra.framework.starter.sms.model.msg.SmsMsgRequest;
import com.guosen.zebra.framework.starter.sms.model.msg.SmsMsgResponse;
import com.guosen.zebra.framework.starter.sms.service.SmsMessageService;
import com.guosen.zebra.framework.starter.sms.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Optional;

import static com.guosen.zebra.framework.starter.sms.constants.SmsExceptionMessage.*;
import static com.guosen.zebra.framework.starter.sms.constants.SmsFields.SYSTEM;
import static com.guosen.zebra.framework.starter.sms.constants.SmsFields.TOKEN;

/**
 * SMS短信服务实现
 */
@Slf4j
public class SmsMessageServiceImpl implements SmsMessageService {

    private final SmsProperties smsProperties;

    public SmsMessageServiceImpl(SmsProperties smsProperties) {
        this.smsProperties = smsProperties;
    }

    @Override
    public SmsMsgResponse sendMessage(SmsMsgRequest request) {
        return sendMessage(SmsApis.SEND_MESSAGE.getApi(), request);
    }

    @Override
    public SmsMsgResponse sendMessageAndReturnId(SmsMsgRequest request) {
        return sendMessage(SmsApis.SEND_MESSAGE_AND_RETURN_ID.getApi(), request);
    }

    @Override
    public SmsMsgResponse sendMessageByFundIds(SmsMsgRequest request) {
        return sendMessage(SmsApis.SEND_MESSAGE_BY_FUNDIDS.getApi(), request);
    }

    public SmsMsgResponse sendMessage(String api, SmsMsgRequest request) {
        String url = smsProperties.getAddress() + api;
        JsonNode result;
        Map<String, String> formData = buildMap(request);
        try {
            result = SmsHttpClient.post(url, formData);
            log.info("[SMS] sms message sending success.");
        } catch (SmsException e) {
            log.error("[SMS] Sms message sending is failed, request:{}, error message:{}.", request, e.getMessage());
            throw new SmsException(SEND_SMS_FAILED, e);
        }
        try {
            return JsonUtil.getObjectMapper().treeToValue(result, SmsMsgResponse.class);
        } catch (JsonProcessingException e) {
            log.error("[SMS] Sms message's response resolving is failed, request:{}, error message:{}.", request, e.getMessage());
            throw new SmsException(RESPONSE_RESOLVE_FAILED + result, e);
        }
    }

    public Map<String, String> buildMap(Object obj) {
        try {
            Map<String, String> map = JsonUtil.getObjectMapper().convertValue(obj, new TypeReference<Map<String, String>>() {
            });
            return addTokenAndSystem(map);
        } catch (Exception e) {
            throw new SmsException(REQUEST_RESOLVE_FAILED, e);
        }
    }

    public Map<String, String> addTokenAndSystem(Map<String, String> map) {
        map.computeIfAbsent(TOKEN, key -> Optional.ofNullable(smsProperties.getToken()).orElse(""));
        map.computeIfAbsent(SYSTEM, key -> Optional.ofNullable(smsProperties.getSystem()).orElse(""));
        return map;
    }
}
